package com.atguigu.gmall.filter;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
public class AuthFilter implements GlobalFilter {

    @Value("${authUrls.url}")
    private String authUrlsUrl;
    @Autowired
    private RedisTemplate redisTemplate;
    private AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求
        ServerHttpRequest request = exchange.getRequest();
        //获取响应
        ServerHttpResponse response = exchange.getResponse();

        //获取请求路径
        String path = request.getURI().getPath();
        //释放静态资源
        if (antPathMatcher.match("/**/css/**",path) || antPathMatcher.match("/**/js/**",path)
                || antPathMatcher.match("/**/img/**",path)){
            //  放行，执行下一个过滤器；
            chain.filter(exchange);
        }
        //拦截内部资源
        if (antPathMatcher.match("/**/inner/**", path)) {
            return out(response, ResultCodeEnum.PERMISSION);
        }
        //获取用户id
        String userId = getUserId(request);
        //获取临时用户Id
        String userTempId = getUserTempId(request);
        //判断是否访问auth路径
        if (antPathMatcher.match("/**/auth/**", path)) {
            if (StringUtils.isEmpty(userId)) {
                return out(response, ResultCodeEnum.LOGIN_AUTH);
            }
        }
        //限制用户哪些业务需要登录
        //获取需要拦截的业务数组
        String[] split = authUrlsUrl.split(",");
        if (split != null && split.length > 0) {
            for (String url : split) {
                //判断需要登录的业务，并且没有登录的情况下
                if (path.indexOf(url) != -1 && StringUtils.isEmpty(userId)) {
                    response.setStatusCode(HttpStatus.SEE_OTHER);
                    response.getHeaders().set(HttpHeaders.LOCATION,"http://passport.gmall.com/login.html?originUrl="+request.getURI());

                    return response.setComplete();
                }

            }
        }
        //判断
        if (!StringUtils.isEmpty(userTempId)) {
            request.mutate().header("userTempId", userTempId);
        }
        if (!StringUtils.isEmpty(userId)) {
            request.mutate().header("userId", userId);
        }

        return chain.filter(exchange);
    }

    private String getUserTempId(ServerHttpRequest request) {
        String userTempId = "";
        //获取cookie信息
        HttpCookie httpCookie = request.getCookies().getFirst("userTempId");
        if (httpCookie != null) {
            //如果cookie中存在就从cookie中获取
            userTempId = httpCookie.getValue();
        }else {
            //如果cookie中不存在，就去请求头中获取
            List<String> tokenList = request.getHeaders().get("userTempId");
            if (!CollectionUtils.isEmpty(tokenList)) {
                userTempId = tokenList.get(0);
            }
        }
        return userTempId;
    }

    /**
     * 获取用户ID
     * @param request
     * @return
     */
    private String getUserId(ServerHttpRequest request) {
        String token = "";
        //获取cookie信息
        HttpCookie httpCookie = request.getCookies().getFirst("token");
        if (httpCookie != null) {
            //如果cookie中存在就从cookie中获取
            token = httpCookie.getValue();
        }else {
            //如果cookie中不存在，就去请求头中获取
            List<String> tokenList = request.getHeaders().get("token");
            if (!CollectionUtils.isEmpty(tokenList)) {
                token = tokenList.get(0);
            }
        }
        //获取缓存key
        String loginKey = "user:login:" + token;
        //从缓存中获取数据
        JSONObject userJson = (JSONObject) redisTemplate.opsForValue().get(loginKey);
        if (userJson!=null){
            //将数据转换成JSONObject;
            String ip = (String) userJson.get("ip");
            //如果ip地址一样再去获取用户id
            if (ip.equals(IpUtil.getGatwayIpAddress(request))) {
                String userId = (String) userJson.get("userId");
                return userId;
            } else {
                //非法盗用
                return "-1";
            }
        }
        return "";
    }

    /**
     * 输出信息
     * @param response
     * @param resultCodeEnum
     * @return
     */
    private Mono<Void> out(ServerHttpResponse response, ResultCodeEnum resultCodeEnum) {
        //获取提示信息
        Result<Object> result = Result.build(null, resultCodeEnum);
        byte[] bytes = JSONObject.toJSONString(result).getBytes();
        DataBuffer wrap = response.bufferFactory().wrap(bytes);
        response.getHeaders().add("Content-Type","application/json;charset=utf-8");
        return response.writeWith(Mono.just(wrap));
    }
}
